/**********************************************************************
 *File		:	key.c
 *Time		:	2023/6/7
 *Author		:	Bryan He（贺璧）
 *Discreption:
 *
 ************************************************************************/
#include "stm32f0xx_hal.h"
#include "stm32f0xx_hal_def.h"
#include "stm32f0xx_hal_gpio.h"
#include "stm32f0xx_hal_i2c.h"
#include "mo_button.h"
#include "key.h"

/*@TODO: You have to config below items which depend on your hardware cfg and which MCU you used.*/
#define key_get_gpio_state(port,pin)  HAL_GPIO_ReadPin(port,pin)

static KEY_TASK_T k_task;

const ExKyeInfo ex_key_map[GPIO_KEY_MAX] = {
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
    {
        .kcode = HW_KEY_NULL,
        .port = 0,
        .pin = 0,
    },
};

static void app_key_task_handle(mo_task tsk, mo_msg_id id, mo_msg msg) {
    GPIO_PinState pio;
    u8 j;

    switch (id) {
        case USR_EVENT_IO_KEY_POLLING:
            for (j = 0; j < GPIO_KEY_MAX; j++) {
                if (k_task.pKeyTable[j].port != 0) {
                    pio = key_get_gpio_state((GPIO_TypeDef*)k_task.pKeyTable[j].port, k_task.pKeyTable[j].pin);
                    if (pio == GPIO_PIN_SET) { /*Up*/
                        if (k_task.ex_k_cnt[j] != 0) {
                            k_task.ex_k_cnt[j]--;
                            if (k_task.ex_k_cnt[j] == 0) {
                                mo_send_a_vk_to_btn_task(SYS_EVENT_VK_UP, k_task.pKeyTable[j].kcode);
                            }
                        }
                    } else { /*Down*/
                        if (k_task.ex_k_cnt[j] < KEY_DEBOUNCE_TIME) {
                            k_task.ex_k_cnt[j]++;
                            if (k_task.ex_k_cnt[j] >= KEY_DEBOUNCE_TIME) {
                                mo_send_a_vk_to_btn_task(SYS_EVENT_VK_DOWN, k_task.pKeyTable[j].kcode);
                            }
                        }
                    }
                }
            }
            mo_msg_cancel_all(tsk, USR_EVENT_IO_KEY_POLLING);
            mo_msg_send(tsk, USR_EVENT_IO_KEY_POLLING, NULL, KEY_POLLING_INTERVAL);
            break;

        default:
            break;
    }
}

void app_key_task_init(void) {
  memset(&k_task, 0, sizeof(k_task));
  k_task.tsk.handler = app_key_task_handle;
  k_task.pKeyTable = ex_key_map;
  mo_msg_send(&k_task.tsk, USR_EVENT_IO_KEY_POLLING, NULL, KEY_POLLING_INTERVAL);
}

const mo_task get_key_tsk(void) { return &k_task.tsk; }

/**************************************************************/